﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using PSE.Tools.SchemaComparer.Comparer;

namespace PSE.Tools.SchemaComparer.WindowsApp
{
    /// <summary>
    /// Interaction logic for CompareResultView.xaml
    /// </summary>
    public partial class CompareResultView : Window
    {


        public string WindowTitle
        {
            get { return (string)GetValue(WindowTitleProperty); }
            set { SetValue(WindowTitleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for WindowTitle.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty WindowTitleProperty =
            DependencyProperty.Register("WindowTitle", typeof(string), typeof(CompareResultView), new UIPropertyMetadata(string.Empty));


        DBSchemaCompareResult _compareResult;

        Configurations _config;

        public CompareResultView(DBSchemaCompareResult compareResult)
        {
            InitializeComponent();
            if (compareResult == null)
                throw new ArgumentNullException("compareResult");

            _compareResult = compareResult;

            this.DataContext = this;
            this.Title = string.Format("Resultado da Comparação entre os Schemas {0} e {1}", _compareResult.SourceSchemaName, _compareResult.TargetSchemaName);
            this.Loaded += new RoutedEventHandler(CompareResultView_Loaded);
        }

        void CompareResultView_Loaded(object sender, RoutedEventArgs e)
        {
            _config = new Configurations();
            _config.Load();

            LoadTreeViewNodes();
        }

        private void LoadTreeViewNodes()
        {
            if (_compareResult.HasDiferences)
            {
                TreeViewItem rootNode;

                //criar o no raiz
                rootNode = new TreeViewItem();
                rootNode.Header = string.Format("{0} x {1}",
                                    _compareResult.SourceSchemaName, _compareResult.TargetSchemaName);

                tvResultView.Items.Add(rootNode);

                TreeViewItem node = CreateCompareResultNode(_compareResult.TableCompareResults);
                if (node != null)
                    tvResultView.Items.Add(node);

                node = CreateCompareResultNode(_compareResult.ViewCompareResults);
                if (node != null)
                    tvResultView.Items.Add(node);

                node = CreateCompareResultNode(_compareResult.SequenceCompareResults);
                if (node != null)
                    tvResultView.Items.Add(node);

                node = CreateCompareResultNode(_compareResult.SynonymCompareResults);
                if (node != null)
                    tvResultView.Items.Add(node);

                node = CreateCompareResultNode(_compareResult.PackageCompareResults);
                if (node != null)
                    tvResultView.Items.Add(node);

                node = CreateCompareResultNode(_compareResult.ProcedureCompareResults);
                if (node != null)
                    tvResultView.Items.Add(node);

                node = CreateCompareResultNode(_compareResult.FunctionCompareResults);
                if (node != null)
                    tvResultView.Items.Add(node);

                //criar nos relacionados aos tipos de comparacoes realizadas
                //criar items relacionados a comparacao de tabelas
            }
            else
            {
                TreeViewItem node;

                //criar o no raiz
                node = new TreeViewItem();
                node.Header = string.Format("Não foram encontradas diferenças entre os Schemas {0} e {1}",
                                _compareResult.SourceSchemaName, _compareResult.TargetSchemaName);
                tvResultView.Items.Add(node);
            }
        }


        private TreeViewItem CreateCompareResultNode(List<DBObjectCompareResult> objectCompareResultList)
        {
            TreeViewItem rootNode = null;

            TreeViewItem tvi0 = null;

            objectCompareResultList.Sort(CompareDBObjectCompareResultByStatus);

            foreach (DBObjectCompareResult resultItem in objectCompareResultList)
            {
                if (rootNode == null)
                {
                    rootNode = new TreeViewItem();
                    rootNode.Header = string.Format("{0} ({1})", resultItem.ObjectType, objectCompareResultList.Count);
                }

                switch (resultItem.CompareStatus)
                {
                    case DBObjectCompareStatus.ObjectHasDiferences:
                        {
                            tvi0 = new TreeViewItem();
                            tvi0.Header = resultItem.ObjectName;

                            TreeViewItem tvi1;
                            TreeViewItem tvi2;
                            TreeViewItem tvi3;
                            //montar os items com as propriedades do objetos
                            foreach (PropertyCompareResult propCompRes in resultItem.PropertyCompareResults)
                            {
                                tvi1 = new TreeViewItem();
                                tvi1.Header = propCompRes.PropertyName;

                                tvi2 = new TreeViewItem();
                                tvi2.Header = new UcPropertyCompareResultItem(this, _config, _compareResult.SourceSchemaName, propCompRes.SourceValue, _compareResult.TargetSchemaName, propCompRes.TargetValue);

                                tvi1.Items.Add(tvi2);
                                tvi0.Items.Add(tvi1);
                            }
                            //montar os itens com os objetos relacionados
                            //resultItem.RelatedObjects
                            foreach (List<DBObjectCompareResult> relatedObjecCompRes in resultItem.RelatedObjects)
                            {
                                tvi3 = CreateCompareResultNode(relatedObjecCompRes);
                                tvi0.Items.Add(tvi3);
                            }
                        }
                        break;
                    case DBObjectCompareStatus.ObjectExistOnlyInSourceSchema:
                        {
                            tvi0 = new TreeViewItem();
                            tvi0.Header = resultItem.ObjectName + " - " + "Existente apenas no Schema " + _compareResult.SourceSchemaName;
                            //TODO: atribuir uma cor ao item
                        }
                        break;
                    case DBObjectCompareStatus.ObjectExistOnlyInTargetSchema:
                        {
                            tvi0 = new TreeViewItem();
                            tvi0.Header = resultItem.ObjectName + " - " + "Existente apenas no Schema " + _compareResult.TargetSchemaName;
                            //TODO: atribuir uma cor ao item
                        }
                        break;
                }

                if (tvi0 != null)
                    rootNode.Items.Add(tvi0);
            }

            return rootNode;
        }

        private static int CompareDBObjectCompareResultByStatus(DBObjectCompareResult a, DBObjectCompareResult b)
        {
            return a.CompareStatus.CompareTo(b.CompareStatus) * -1;
        }

    }
}
